package com.ys.erp.stage_mall_service.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.*;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_mall_service.bean.condition.OrderCondition;
import com.ys.erp.stage_mall_service.bean.vo.OrderDetailVO;
import com.ys.erp.stage_mall_service.bean.vo.OrderGoodsVO;
import com.ys.erp.stage_mall_service.bean.vo.OrderVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @author lwj
 * @date 2025/5/19
 */
@Service
@RequiredArgsConstructor
@Slf4j
@RefreshScope
public class OrderService {

    private final IOrderService iOrderService;

    private final IUserService iUserService;

    private final IOrderGoodsService iOrderGoodsService;

    private final IToShopOrderService iToShopOrderService;

    private final IShopService iShopService;

    /**
     * 分页订单
     *
     * @param con               请求体
     * @return                  订单数据
     */
    public PageDTO<OrderVO> pageOrder(OrderCondition.PageOrderCon con) {
        Page<Order> orderPage = new Page<>(con.getCurrent(), con.getSize());
        QueryWrapper<Order> qw = generateOrderQw(con);

        Page<Order> page = iOrderService.page(orderPage, qw);
        //查询goods
        List<Long> orderIds = page.getRecords().stream().map(Order::getId).collect(Collectors.toList());
        if (orderIds.isEmpty()) {
            return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        CompletableFuture<Map<Long, ToShopOrder>> toShopOrderMapFuture = YsThread.execute(() -> {
            QueryWrapper<ToShopOrder> toShopOrderQw = new QueryWrapper<>();
            toShopOrderQw.lambda().in(ToShopOrder::getOrderId, orderIds);
            return iToShopOrderService.list(toShopOrderQw).stream()
                    .collect(Collectors.toMap(ToShopOrder::getOrderId, it -> it));
        });
        List<Long> userIds = page.getRecords().stream()
                .map(Order::getUserId)
                .collect(Collectors.toList());
        CompletableFuture<Map<Long, User>> userMapFuture = YsThread.execute(() -> {
            return iUserService.listByIds(userIds).stream()
                    .collect(Collectors.toMap(User::getId, it -> it));
        });
        CompletableFuture<Map<Long, List<OrderGoods>>> orderGoodsMapFuture = YsThread.execute(() -> {
            QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
            orderGoodsQw.lambda().in(OrderGoods::getOrderId, orderIds);
            return iOrderGoodsService.list(orderGoodsQw).stream()
                    .collect(Collectors.groupingBy(OrderGoods::getOrderId));
        });
        Map<Long, ToShopOrder> toShopOrderMap = toShopOrderMapFuture.join();
        Map<Long, User> userMap = userMapFuture.join();
        Map<Long, List<OrderGoods>> orderGoodsMap = orderGoodsMapFuture.join();
        List<OrderVO> collect = page.getRecords().stream()
                .map(it -> {
                    OrderVO vo = new OrderVO();
                    BeanUtils.copyProperties(it, vo);
                    vo.setTotalMoney(MoneyUtil.long2Str(it.getTotalMoney()));
                    vo.setFreightMoney(MoneyUtil.long2Str(it.getFreightMoney()));
                    vo.setDiscountMoney(MoneyUtil.long2Str(it.getDiscountMoney()));
                    vo.setPayType(it.getPayType());
                    vo.setYsPulseMoney(MoneyUtil.long2Str(it.getYsPulseMoney()));
                    vo.setWxPayMoney(MoneyUtil.long2Str(it.getActualWxMoney()));
                    vo.setYsPayMoney(MoneyUtil.long2Str(it.getActualYsMoney()));
                    vo.setIsPersonPay(it.getIsPersonPay());
                    vo.setDeliveryType(it.getDeliveryType());
                    vo.setOrderType(it.getGoodsType());
                    vo.setOrderGoodsList(new ArrayList<>());
                    ToShopOrder toShopOrder = toShopOrderMap.get(it.getId());
                    if (ObjectUtils.isNotEmpty(toShopOrder)) {
                        vo.setSendShopName(toShopOrder.getShopName());
                    }
                    if (orderGoodsMap.containsKey(it.getId())) {
                        List<OrderGoodsVO> orderGoodsVOList = orderGoodsMap.get(it.getId()).stream()
                                .map(childIt -> {
                                    OrderGoodsVO orderGoodsVO = new OrderGoodsVO();
                                    BeanUtils.copyProperties(childIt, orderGoodsVO);
                                    orderGoodsVO.setDeliveryMoney(MoneyUtil.long2Str(childIt.getDeliveryMoney()));
                                    orderGoodsVO.setSubtotal(MoneyUtil.long2Str(childIt.getSubtotal()));
                                    orderGoodsVO.setGoodsSpecs(childIt.getSpecsDes());
                                    return orderGoodsVO;
                                }).collect(Collectors.toList());
                        vo.setOrderGoodsList(orderGoodsVOList);
                    }
                    User user = userMap.get(it.getUserId());
                    if (Objects.isNull(user)) {
                        return vo;
                    }
                    OrderVO.OrderUserVO userVO = new OrderVO.OrderUserVO();
                    BeanUtils.copyProperties(userMap.get(it.getUserId()), userVO);
                    vo.setUser(userVO);
                    return vo;
                }).collect(Collectors.toList());
        return new PageDTO<>(page.getCurrent(), page.getTotal(), collect);
    }

    private QueryWrapper<Order> generateOrderQw(OrderCondition.PageOrderCon con) {
        QueryWrapper<Order> qw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(con.getStatus())) {
            if (con.getStatus() == 6) {
                qw.lambda().eq(Order::getIsUserCancel, EnableEnum.YES.getEnable())
                        .eq(Order::getIsCancel, EnableEnum.NO.getEnable());
            } else if (con.getStatus() == 5) {
                qw.lambda().eq(Order::getIsCancel, EnableEnum.YES.getEnable());
            } else {
                qw.lambda().eq(Order::getOrderStatus, con.getStatus())
                        .eq(Order::getIsUserCancel, EnableEnum.NO.getEnable())
                        .eq(Order::getIsCancel, EnableEnum.NO.getEnable());
            }
        }
        if (ObjectUtils.isNotEmpty(con.getCampId())) {
            qw.lambda().eq(Order::getCampId, con.getCampId());
        }
        if (ObjectUtils.isNotEmpty(con.getOrderNo())) {
            qw.lambda().eq(Order::getOrderSerialNumber, con.getOrderNo());
        }
        if (ObjectUtils.isNotEmpty(con.getGoodsType())) {
            qw.lambda().eq(Order::getGoodsType, con.getGoodsType());
        }
        if (ObjectUtils.isNotEmpty(con.getPayType())) {
            // 先确保订单已支付
            qw.lambda().isNotNull(Order::getPayTime);
            
            if (con.getPayType() == 2) {
                // 组合支付，需要包含多个支付方式
                qw.lambda().like(Order::getPayType, ",");
            } else if (con.getPayType() == 3) {
                // 幺豆抵扣
                qw.lambda().gt(Order::getYsPulseMoney, 0);
            } else {
                // 单一支付方式：0=微信支付，1=幺币支付
                qw.lambda().eq(Order::getPayType, con.getPayType())
                         .notLike(Order::getPayType, ","); // 确保不包含组合支付
            }
        }
        if (ObjectUtils.isNotEmpty(con.getOrderAttr())) {
            qw.lambda().eq(Order::getOrderAttr, con.getOrderAttr());
        }
        if (ObjectUtils.isNotEmpty(con.getUserId())) {
            qw.lambda().eq(Order::getUserId, con.getUserId());
        } else {
            qw.lambda().ge(Order::getCreateTime, LocalDateTime.now().minusDays(60));
        }
        if (ObjectUtils.isNotEmpty(con.getUserRemark())) {
            qw.lambda().like(Order::getUserRemark, con.getUserRemark());
        }
        if (ObjectUtils.isNotEmpty(con.getDeliveryName())) {
            qw.lambda().like(Order::getDeliveryName, con.getDeliveryName());
        }
        if (ObjectUtils.isNotEmpty(con.getDeliveryPhone())) {
            qw.lambda().like(Order::getDeliveryPhone, con.getDeliveryPhone());
        }
        if (ObjectUtils.isNotEmpty(con.getDiscountType())) {
            qw.lambda().eq(Order::getIsCancel, EnableEnum.NO.getEnable());
            if (con.getDiscountType() == 0) {
                //优惠券筛选
                qw.lambda().isNotNull(Order::getUserCouponId);
            }
            if (con.getDiscountType() == 1) {
                //幺豆筛选
                qw.lambda().gt(Order::getYsPulseMoney, 0);
            }
        }
        if (ObjectUtils.isNotEmpty(con.getStartTime()) && ObjectUtils.isNotEmpty(con.getEndTime())) {
            qw.lambda().le(Order::getOrderTime, con.getEndTime() + " 23:59:59");
            qw.lambda().ge(Order::getOrderTime, con.getStartTime() + " 23:59:59");
        }
        if (ObjectUtils.isNotEmpty(con.getIsPriceDesc())) {
            if (con.getIsPriceDesc() == EnableEnum.YES.getEnable()) {
                qw.lambda().orderByDesc(Order::getActualMoney);
            } else {
                qw.lambda().orderByAsc(Order::getActualMoney);
            }
        } else {
            qw.lambda().orderByDesc(Order::getId);
        }
        return qw;
    }

    /**
     * 查询订单详情
     *
     * @param orderId               订单id
     * @return                      订单详情
     */
    public OrderDetailVO getOrderDetail(Long orderId) {
        Order byId = iOrderService.getById(orderId);
        if (ObjectUtils.isEmpty(byId)) {
            throw new YsException(-1, "订单不存在");
        }
        CompletableFuture<Shop> personPayShopFuture = YsThread.execute(() -> {
            if (byId.getIsPersonPay() == EnableEnum.YES.getEnable()) {
                return iShopService.getByCode(byId.getPersonPayShopCode());
            }
            return new Shop();
        });
        //查询商品
        CompletableFuture<List<OrderGoods>> orderGoodsListFuture = YsThread.execute(() -> {
            QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
            orderGoodsQw.lambda().eq(OrderGoods::getOrderId, byId.getId());
            return iOrderGoodsService.list(orderGoodsQw);
        });
        //查询用户
        CompletableFuture<User> userFuture = YsThread.execute(() -> {
            return iUserService.getById(byId.getUserId());
        });
        User user = userFuture.join();
        List<OrderGoods> orderGoodsList = orderGoodsListFuture.join();
        Shop personPayShop = personPayShopFuture.join();
        OrderDetailVO orderVo = new OrderDetailVO();
        BeanUtils.copyProperties(byId, orderVo);
        orderVo.setTotalMoney(MoneyUtil.long2Str(byId.getTotalMoney()));
        orderVo.setFreightMoney(MoneyUtil.long2Str(byId.getFreightMoney()));
        orderVo.setDiscountMoney(MoneyUtil.long2Str(byId.getDiscountMoney()));
        orderVo.setActualMoney(MoneyUtil.long2Str(byId.getActualMoney()));
        OrderDetailVO.OrderUserVO userVO = new OrderDetailVO.OrderUserVO();
        BeanUtils.copyProperties(user, userVO);
        orderVo.setUser(userVO);
        orderVo.setPayType(byId.getPayType());
        orderVo.setYsPayMoney(MoneyUtil.long2Str(byId.getActualYsMoney()));
        orderVo.setWxPayMoney(MoneyUtil.long2Str(byId.getActualWxMoney()));
        orderVo.setYsPulseMoney(MoneyUtil.long2Str(byId.getYsPulseMoney()));
        orderVo.setYsPulseNum(MoneyUtil.long2Str(byId.getYsPulseNum()));
        orderVo.setOrderGoodsList(new ArrayList<>());
        orderVo.setUserRemark(byId.getUserRemark());
        if (byId.getIsPersonPay() == EnableEnum.YES.getEnable() && ObjectUtils.isNotEmpty(personPayShop.getName())) {
            orderVo.setPersonPayShopName(personPayShop.getName());
        }
        AtomicLong totalMoney = new AtomicLong(0L);
        List<OrderGoodsVO> collect = orderGoodsList.stream()
                .map(it -> {
                    OrderGoodsVO orderGoodsVO = new OrderGoodsVO();
                    BeanUtils.copyProperties(it, orderGoodsVO);
                    orderGoodsVO.setDeliveryMoney(MoneyUtil.long2Str(it.getDeliveryMoney()));
                    orderGoodsVO.setSubtotal(MoneyUtil.long2Str(it.getSubtotal()));
                    orderGoodsVO.setGoodsSpecs(it.getSpecsDes());
                    totalMoney.addAndGet(it.getSubtotal());
                    return orderGoodsVO;
                }).collect(Collectors.toList());
        orderVo.setOrderGoodsList(collect);
        orderVo.setGoodsTotalMoney(MoneyUtil.long2Str(totalMoney.longValue()));
        return orderVo;
    }
}
